package com.bytenebula.asteroid;

import com.bytenebula.asteroid.entity.MetaDatabase;
import com.bytenebula.asteroid.service.MetaDatabaseService;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * 定义动态数据源对象，用于管理多数据源连接
 */
@Component
public class DynamicDataSource {

    @Autowired
    public void setDatabaseService(MetaDatabaseService databaseService) {
        DynamicDataSource.databaseService = databaseService;
    }

    protected static MetaDatabaseService databaseService;
    private static final Map<String, HikariDataSource> datasources = new HashMap<>();

    public static Connection getConnection(String db_name)
            throws SQLException, MalformedURLException, ClassNotFoundException, InvocationTargetException,
            NoSuchMethodException, InstantiationException, IllegalAccessException {
        if (datasources.containsKey(db_name)) {
            HikariDataSource ds = datasources.get(db_name);
            if (ds.isRunning()) {
                return ds.getConnection();
            }
        }
        MetaDatabase db = databaseService.getByName(db_name);
        if (db != null) {
            HikariDataSource ds = DynamicJdbcDriverLoaderService.createDataSource(db);
            datasources.put(db_name, ds);
            return ds.getConnection();
        }

        return null;
    }

    public static ResultSet executeQuery(String ds_name, String sql)
            throws MalformedURLException, SQLException, ClassNotFoundException, InvocationTargetException,
            NoSuchMethodException, InstantiationException, IllegalAccessException {
        Connection connection = getConnection(ds_name);
        if (connection != null) {
            PreparedStatement stmt = connection.prepareStatement(sql);
            return stmt.executeQuery();
        }
        return null;
    }
}
